DDLGenerator.java
package org.codefilarete.stalactite.sql.ddl;
import java.util.*;
import org.codefilarete.stalactite.sql.DMLNameProviderFactory;
import org.codefilarete.stalactite.sql.ddl.structure.Sequence;
import org.codefilarete.stalactite.sql.ddl.structure.UniqueConstraint;
import org.codefilarete.tool.collection.Collections;
import org.codefilarete.tool.collection.KeepOrderSet;
import org.codefilarete.stalactite.sql.ddl.structure.ForeignKey;
import org.codefilarete.stalactite.sql.ddl.structure.Index;
import org.codefilarete.stalactite.sql.ddl.structure.Table;
/**
* A class to collect multiple DDL sources. Main purpose is multiple table creation scripts so they can be played against a database to deploy
* a schema. Use cases are tests and installation of a new application.
*
* @author Guillaume Mary
* @see DDLDeployer
*/
public class DDLGenerator implements DDLProvider {
private Set<Table<?>> tables = new KeepOrderSet<>();
private Set<Sequence> sequences = new KeepOrderSet<>();
private Set<DDLProvider> ddlProviders = new KeepOrderSet<>();
private final DDLTableGenerator ddlTableGenerator;
private final DDLSequenceGenerator ddlSequenceGenerator;
/**
* Simple generator where column SQL types are took from given Java-SQL type mapping.
* Name of tables and columns are given by a default {@link org.codefilarete.stalactite.query.builder.DMLNameProvider}
*
* @param sqlTypeRegistry the mapping to be used to get SQL type of columns
*/
public DDLGenerator(SqlTypeRegistry sqlTypeRegistry, DMLNameProviderFactory dmlNameProviderFactory) {
this.ddlTableGenerator = new DDLTableGenerator(sqlTypeRegistry, dmlNameProviderFactory);
this.ddlSequenceGenerator = new DDLSequenceGenerator(dmlNameProviderFactory);
}
public DDLGenerator(DDLTableGenerator ddlTableGenerator, DDLSequenceGenerator ddlSequenceGenerator) {
this.ddlTableGenerator = ddlTableGenerator;
this.ddlSequenceGenerator = ddlSequenceGenerator;
}
public DDLTableGenerator getDdlTableGenerator() {
return ddlTableGenerator;
}
public void setTables(Set<? extends Table<?>> tables) {
this.tables = (Set<Table<?>>) tables;
}
public void addTables(Collection<? extends Table<?>> tables) {
this.tables.addAll(tables);
}
public void addTables(Table<?> table, Table<?>... tables) {
this.tables.add(table);
this.tables.addAll(Arrays.asList(tables));
}
public void setSequences(Set<Sequence> sequences) {
this.sequences = sequences;
}
public void addSequences(Sequence sequence, Sequence... sequences) {
this.sequences.add(sequence);
this.sequences.addAll(Arrays.asList(sequences));
}
public void addSequences(Collection<? extends Sequence> sequences) {
this.sequences.addAll(sequences);
}
public void setDDLProviders(Set<DDLProvider> ddlParticipants) {
this.ddlProviders = ddlParticipants;
}
public void addDDLProviders(DDLProvider ddlParticipant, DDLProvider... ddlParticipants) {
this.ddlProviders.add(ddlParticipant);
this.ddlProviders.addAll(Arrays.asList(ddlParticipants));
}
public void addDDLProviders(Collection<? extends DDLProvider> ddlParticipants) {
this.ddlProviders.addAll(ddlParticipants);
}
@Override
public List<String> getCreationScripts() {
// DDLParticipants is supposed to be post treatments (creation of sequences, triggers, ...)
return Collections.cat(generateTableCreationScripts(), generateSequencesCreationScripts(), generateDDLProvidersCreationScripts());
}
protected List<String> generateDDLProvidersCreationScripts() {
List<String> participantsScripts = new ArrayList<>();
for (DDLProvider ddlProvider : ddlProviders) {
participantsScripts.addAll(ddlProvider.getCreationScripts());
}
return participantsScripts;
}
protected List<String> generateTableCreationScripts() {
List<String> tableCreationScripts = new ArrayList<>();
List<String> foreignKeysCreationScripts = new ArrayList<>();
List<String> indexesCreationScripts = new ArrayList<>();
List<String> uniqueConstraintsCreationScripts = new ArrayList<>();
for (Table<?> table : tables) {
tableCreationScripts.add(generateCreationScript(table));
foreignKeysCreationScripts.addAll(getForeignKeyCreationScripts(table));
indexesCreationScripts.addAll(generateIndexCreationScripts(table));
uniqueConstraintsCreationScripts.addAll(generateUniqueConstraintCreationScripts(table));
}
// Foreign keys must be after constraints and indexes because some databases require foreign keys to have index on referenced column (MariaDB)
// Since that's only a matter for some databases and other don't care, we set it here, not in a vendor-dedicated DDLGenerator
return Collections.cat(tableCreationScripts, uniqueConstraintsCreationScripts, indexesCreationScripts, foreignKeysCreationScripts);
}
protected String generateCreationScript(Table<?> table) {
return this.ddlTableGenerator.generateCreateTable(table);
}
protected List<String> generateUniqueConstraintCreationScripts(Table<?> table) {
List<String> uniqueConstraintCreationScripts = new ArrayList<>();
for (UniqueConstraint uniqueConstraint : table.getUniqueConstraints()) {
uniqueConstraintCreationScripts.add(generateCreationScript(uniqueConstraint));
}
return uniqueConstraintCreationScripts;
}
protected List<String> generateIndexCreationScripts(Table<?> table) {
List<String> indexesCreationScripts = new ArrayList<>();
for (Index<?> index : table.getIndexes()) {
indexesCreationScripts.add(generateCreationScript(index));
}
return indexesCreationScripts;
}
protected String generateCreationScript(UniqueConstraint uniqueConstraint) {
return this.ddlTableGenerator.generateCreateUniqueConstraint(uniqueConstraint);
}
protected String generateCreationScript(Index<?> index) {
return this.ddlTableGenerator.generateCreateIndex(index);
}
protected List<String> getForeignKeyCreationScripts(Table<?> table) {
List<String> foreignKeysCreationScripts = new ArrayList<>();
for (ForeignKey<?, ?, ?> foreignKey : table.getForeignKeys()) {
foreignKeysCreationScripts.add(generateCreationScript(foreignKey));
}
return foreignKeysCreationScripts;
}
protected String generateCreationScript(ForeignKey<?, ?, ?> foreignKey) {
return this.ddlTableGenerator.generateCreateForeignKey(foreignKey);
}
protected List<String> generateSequencesCreationScripts() {
List<String> sequenceCreationScripts = new ArrayList<>();
for (Sequence sequence : sequences) {
sequenceCreationScripts.add(ddlSequenceGenerator.generateCreateSequence(sequence));
}
return sequenceCreationScripts;
}
@Override
public List<String> getDropScripts() {
// DDLParticipants is supposed to be post treatments (creation of sequences, triggers, ...)
return Collections.cat(generateTableDropScripts(), generateSequencesDropScripts(), generateDDLParticipantsDropScripts());
}
protected List<String> generateTableDropScripts() {
List<String> tableCreationScripts = new ArrayList<>();
for (Table<?> table : tables) {
tableCreationScripts.add(this.ddlTableGenerator.generateDropTable(table));
}
// foreign keys must be after table scripts, index is fine tuning
return tableCreationScripts;
}
protected List<String> generateDDLParticipantsDropScripts() {
List<String> participantsScripts = new ArrayList<>();
for (DDLProvider ddlProvider : ddlProviders) {
List<String> dropScripts = ddlProvider.getDropScripts();
if (!Collections.isEmpty(dropScripts)) {
participantsScripts.addAll(dropScripts);
}
}
return participantsScripts;
}
protected List<String> generateSequencesDropScripts() {
List<String> sequenceCreationScripts = new ArrayList<>();
for (Sequence sequence : sequences) {
sequenceCreationScripts.add(ddlSequenceGenerator.generateDropSequence(sequence));
}
return sequenceCreationScripts;
}
}